home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / games / seahaven / stack.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  11.7 KB  |  530 lines

  1. /*
  2.  * Copyright 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  * Author:  Terry Weissman
  19.  *          weissman@sgi.com
  20.  */
  21.  
  22.  
  23.  
  24. #include "seahaven.h"
  25. #include "auto.h"
  26.  
  27. #include <sys/time.h>        // For time()
  28. #include <malloc.h>
  29. #include <X11/cursorfont.h>
  30.  
  31. #include <math.h>        // For random()
  32.  
  33. Stack playstack[NUMPLAYSTACK];
  34. Stack singlestack[NUMSINGLESTACK];
  35. Stack donestack[NUMSUITS];
  36.  
  37.  
  38. static Stack allstacks[100];
  39. static int numstacks = 0;
  40.  
  41. static int initializing = False;
  42. static int undoing = False;
  43.  
  44. class StackPlayRec : public StackRec {
  45.   public:
  46.     StackPlayRec(int x, int y);
  47.     virtual Bool addCard(Card, AnimType animate = Normal);
  48.     virtual StackType getType();
  49.   private:
  50. };
  51.  
  52.  
  53. class StackSingleRec : public StackRec {
  54.   public:
  55.     StackSingleRec(int x, int y);
  56.     virtual Bool addCard(Card, AnimType animate = Normal);
  57.     virtual StackType getType();
  58.   private:
  59. };
  60.  
  61.  
  62. class StackDoneRec : public StackRec {
  63.   public:
  64.     StackDoneRec(int x, int y);
  65.     virtual Bool addCard(Card, AnimType animate = Normal);
  66.     virtual int getStackingHeight();
  67.     virtual StackType getType();
  68.   private:
  69. };
  70.  
  71.  
  72. UndoListRec::UndoListRec() {
  73.     max = 100;
  74.     cards = (Card *) malloc(max * sizeof(Card));
  75.     stacks = (Stack *) malloc(max * sizeof(Stack));
  76.     clear();
  77. }
  78.  
  79.  
  80. void UndoListRec::clear() {
  81.     num = 0;
  82. }
  83.  
  84. void UndoListRec::add(Card c, Stack s) {
  85.     if (num >= max) {
  86.     max += 100;
  87.     cards = (Card *) realloc((char *) cards, max * sizeof(Card));
  88.     stacks = (Stack *) realloc((char *) stacks, max * sizeof(Stack));
  89.     }
  90.     cards[num] = c;
  91.     stacks[num] = s;
  92.     num++;
  93. }
  94.  
  95. void UndoListRec::addBoundary() {
  96.     if (num > 0 && cards[num - 1] != NULL) add(NULL, NULL);
  97. }
  98.  
  99.  
  100. void UndoListRec::doUndo() {
  101.     initializing = True;    // Hack to fool StackPlayRec::addCard.
  102.     if (num > 0 && cards[num - 1] == NULL) num--;
  103.     while (num > 0 && cards[num - 1] != NULL) {
  104.     num--;
  105.     stacks[num]->addCard(cards[num]);
  106.     }
  107.     initializing = False;
  108.     for (int i=0 ; i<NUMPLAYSTACK ; i++) playstack[i]->repositionAll();
  109. }
  110.  
  111. Bool UndoListRec::isEmpty() {
  112.     for (int i = 0 ; i<num ; i++) if (cards[i]) return False;
  113.     return True;
  114. }
  115.     
  116. UndoListRec undostack;
  117. UndoListRec redostack;
  118.  
  119. void AddUndo(Card c, Stack s) {
  120.     UndoList list = undoing ? &redostack : &undostack;
  121.     list->add(c, s);
  122. }
  123.  
  124.  
  125. void UndoBoundary() {
  126.     undostack.addBoundary();
  127.     redostack.clear();
  128. }
  129.  
  130.  
  131. void DoUndo() {
  132.     undoing = True;
  133.     undostack.doUndo();
  134.     undoing = False;
  135.     redostack.addBoundary();
  136. }
  137.  
  138. void DoRedo() {
  139.     redostack.doUndo();
  140.     undostack.addBoundary();
  141. }
  142.  
  143.  
  144. void DoRestart() {
  145.     while (!undostack.isEmpty()) DoUndo();
  146. }
  147.  
  148. StackRec::StackRec(int newx, int newy) {
  149.     x = newx;
  150.     y = newy;
  151.     numcards = 0;
  152.     allstacks[numstacks++] = this;
  153. }
  154.  
  155. void StackRec::clear() {
  156.     numcards = 0;
  157. }
  158.  
  159. int StackRec::getX() {
  160.     return x;
  161. }
  162.  
  163. int StackRec::getY() {
  164.     return y;
  165. }
  166.  
  167. Card StackRec::getTopCard() {
  168.     if (numcards == 0) return NULL;
  169.     return cards[numcards - 1];
  170. }
  171.  
  172. Card StackRec::getCardAbove(Card c) {
  173.     int i;
  174.     for (i=0 ; i<numcards - 1 ; i++) {
  175.     if (cards[i] == c) return cards[i + 1];
  176.     }
  177.     return NULL;
  178. }
  179.  
  180.  
  181. static int Abs(int x) {
  182.     return (x < 0) ? -x : x;
  183. }
  184.  
  185.  
  186. static int Max(int a, int b) {
  187.     return (a > b) ? a : b;
  188. }
  189.  
  190.  
  191. void StackRec::repositionAll() {
  192.     for (int i=0 ; i<numcards ; i++) {
  193.     cards[i]->setLoc(x, y + i * getStackingHeight());
  194.     }
  195. }
  196.  
  197. Card StackRec::popCard() {
  198.     if (numcards == 0) return NULL;
  199.     numcards--;
  200.     return cards[numcards];
  201. }
  202.  
  203. Bool StackRec::addCard(Card c, AnimType animate) {
  204.     if (c->getStack() == this) Punt("Error in StackRec::addCard!");
  205.     if (animate == Animate) {
  206.     c->raise();
  207.     int oldx = c->getX();
  208.     int oldy = c->getY();
  209.     int newx = x;
  210.     int newy = y + numcards * getStackingHeight();
  211.     int numsteps = Max(Abs(oldx - newx), Abs(oldy - newy)) / speedup;
  212.     float curx = (float) oldx;
  213.     float cury = (float) oldy;
  214.     for (int i = 0 ; i<numsteps ; i++) {
  215.         curx += ((float) (newx - oldx)) / numsteps;
  216.         cury += ((float) (newy - oldy)) / numsteps;
  217.         c->setLoc((int) curx, (int) cury);
  218.         XFlush(dpy);
  219.     }
  220.     }
  221.     if (animate != DontMove) {
  222.     if (numcards > 0) c->raiseAbove(cards[numcards - 1]);
  223.     c->setLoc(x, y + numcards * getStackingHeight());
  224.     if (inautoplay) XFlush(dpy);
  225.     }
  226.     Stack old = c->getStack();
  227.     if (old && old->popCard() != c) {
  228.     Punt("Couldn't find card in old stack in StackRec::addCard!");
  229.     }
  230.     AddUndo(c, c->getStack());
  231.     c->setStack(this);
  232.     cards[numcards++] = c;
  233.     return True;
  234. }
  235.  
  236.  
  237. int StackRec::getStackingHeight() {
  238.     return 34;
  239. }
  240.  
  241. StackType StackRec::getType() {
  242.     Punt("Invalid call to base class: StackRec::getType()");
  243.     return Single;
  244. }
  245.  
  246. StackPlayRec::StackPlayRec(int x, int y) : StackRec(x, y) {
  247. }
  248.  
  249.  
  250. Bool StackPlayRec::addCard(Card c, AnimType animate) {
  251.     if (!initializing) {
  252.     if (numcards == 0) {
  253.         if (c->getValue() != NUMVALUES - 1) return False;
  254.     } else {
  255.         if (c->getSuit() != cards[numcards - 1]->getSuit() ||
  256.            c->getValue() != cards[numcards - 1]->getValue() - 1)
  257.         return False;
  258.     }
  259.     }
  260.     return StackRec::addCard(c, animate);
  261. }
  262.  
  263. StackType StackPlayRec::getType() {
  264.     return Play;
  265. }
  266.  
  267.  
  268. StackSingleRec::StackSingleRec(int x, int y) : StackRec(x, y) {
  269.     XSetWindowAttributes attributes;
  270.     long valuemask = CWBackPixel | CWBorderPixel;
  271.     attributes.background_pixel = GetColor("darkgreen", "grey70",
  272.                        WhitePixel(dpy, screen));
  273.     attributes.border_pixel = GetColor("green", "grey90", BlackPixel(dpy, screen));
  274.     Window w = XCreateWindow(dpy, toplevel, x - 1, y - 1,
  275.                  CARDWIDTH, CARDHEIGHT, 1, (int) CopyFromParent,
  276.                  InputOutput, (Visual *) CopyFromParent,
  277.                  valuemask, &attributes);
  278.     XLowerWindow(dpy, w);
  279.     XMapWindow(dpy, w);
  280. }
  281.  
  282. StackSingleRec::addCard(Card c, AnimType animate) {
  283.     if (numcards) return False;
  284.     return StackRec::addCard(c, animate);
  285. }
  286.  
  287. StackType StackSingleRec::getType() {
  288.     return Single;
  289. }
  290.  
  291.  
  292. StackDoneRec::StackDoneRec(int x, int y) : StackRec(x, y) {
  293. }
  294.  
  295. StackDoneRec::addCard(Card c, AnimType animate) {
  296.     if (numcards == 0) {
  297.     if (c->getValue() != 0) return False;
  298.     } else {
  299.     if (c->getSuit() != cards[numcards - 1]->getSuit() ||
  300.           c->getValue() != cards[numcards - 1]->getValue() + 1)
  301.         return False;
  302.     }
  303.     return StackRec::addCard(c, animate);
  304. }
  305.  
  306. StackDoneRec::getStackingHeight() {
  307.     return 0;
  308. }
  309.  
  310. StackType StackDoneRec::getType() {
  311.     return Done;
  312. }
  313.  
  314.  
  315. static int Random(int i) {
  316.     return random() % i;
  317. }
  318.  
  319.  
  320.  
  321. void AutoMoves() {
  322.     Bool found;
  323.     int i;
  324.     do {
  325.     found = False;
  326.     for (i=0 ; i<numstacks ; i++) {
  327.         Card card = allstacks[i]->getTopCard();
  328.         if (card) {
  329.         Card dcard = donestack[card->getSuit()]->getTopCard();
  330.         if (card->getValue() == (dcard ? dcard->getValue() + 1 : 0)) {
  331.             donestack[card->getSuit()]->addCard(card,
  332.                             inautoplay ? Normal
  333.                             : Animate);
  334.             found = True;
  335.         }
  336.         }
  337.     }
  338.     } while (found);
  339.     for (i=0 ; i<NUMSUITS ; i++) {
  340.     Card card = donestack[i]->getTopCard();
  341.     if (card == NULL ||
  342.         donestack[i]->getTopCard()->getValue() < NUMVALUES - 1) return;
  343.     }
  344.     score->wonGame();
  345. }
  346.  
  347.  
  348. int NumAvailableSingles() {
  349.     int result = 0;
  350.     for (int i=0 ; i<NUMSINGLESTACK ; i++) {
  351.     if (singlestack[i]->getTopCard() == NULL) result++;
  352.     }
  353.     return result;
  354. }
  355.  
  356.  
  357. Stack GetAvailableSingle() {
  358.     for (int i=0 ; i<NUMSINGLESTACK ; i++) {
  359.     if (singlestack[i]->getTopCard() == NULL) return singlestack[i];
  360.     }
  361.     return NULL;
  362. }
  363.  
  364.  
  365. Stack StackFromPoint(int x, int y) {
  366.     Stack *checklist;
  367.     int num;
  368.     if (y < playstack[0]->getY() - 20) {
  369.     checklist = singlestack;
  370.     num = NUMSINGLESTACK;
  371.     } else {
  372.     checklist = playstack;
  373.     num = NUMPLAYSTACK;
  374.     }
  375.     for (int i=0 ; i<num ; i++) {
  376.     if (x >= checklist[i]->getX() - CARDWIDTH / 2 &&
  377.         x < checklist[i]->getX() + CARDWIDTH / 2) return checklist[i];
  378.     }
  379.     return NULL;
  380. }
  381.  
  382.  
  383. void NewGame() {
  384.     int i, j, k, w;
  385.     if (score) {
  386.     score->lostGame();    // Has no effect if wonGame() already called.
  387.     score->newGame();
  388.     }
  389.     initializing = True;
  390.     for (i=0 ; i<numstacks ; i++) {
  391.     allstacks[i]->clear();
  392.     }
  393.     Card deck[NUMSUITS * NUMVALUES];
  394.     i = 0;
  395.     for (int s = 0 ; s < NUMSUITS ; s++) {
  396.     for (int v = 0 ; v < NUMVALUES ; v++) {
  397.         deck[i++] = cards[s][v];
  398.         cards[s][v]->setStack(NULL);
  399.     }
  400.     }
  401.     if (score) score->saveGameBegin();
  402.     for (k=0 ; k<CARDSPERPLAYSTACK ; k++) {
  403.     for (j=0 ; j<NUMPLAYSTACK ; j++) {
  404.         w = Random(i);
  405.         playstack[j]->addCard(deck[w]);
  406.         if (score) score->saveGameCard(deck[w]);
  407.         deck[w] = deck[--i];
  408.     }
  409.     }
  410.     for (j=0 ; j<i ; j++) {
  411.     singlestack[j + 1]->addCard(deck[j]);
  412.     if (score) score->saveGameCard(deck[j]);
  413.     }
  414.     if (score) score->saveGameEnd();
  415.     initializing = False;
  416.  
  417.     AutoMoves();
  418.     undostack.clear();
  419.     redostack.clear();
  420. }
  421.  
  422.  
  423.  
  424. void LoadStacks(Card deck[52]) {
  425.     int i, j, k, w;
  426.     initializing = True;
  427.     for (i=0 ; i<numstacks ; i++) {
  428.     allstacks[i]->clear();
  429.     }
  430.     initializing = True;
  431.     for (int s = 0 ; s < NUMSUITS ; s++) {
  432.     for (int v = 0 ; v < NUMVALUES ; v++) {
  433.         cards[s][v]->setStack(NULL);
  434.     }
  435.     }
  436.     w = 0;
  437.     for (k=0 ; k<CARDSPERPLAYSTACK ; k++) {
  438.     for (j=0 ; j<NUMPLAYSTACK ; j++) {
  439.         playstack[j]->addCard(deck[w++]);
  440.     }
  441.     }
  442.     for (j=0 ; j<2 ; j++) {
  443.     singlestack[j + 1]->addCard(deck[w++]);
  444.     }
  445.     initializing = False;
  446.  
  447.     AutoMoves();
  448.     undostack.clear();
  449.     redostack.clear();
  450. }
  451.  
  452.  
  453. class StackNoticeExitRec {
  454.   public:
  455.     StackNoticeExitRec() {}
  456.     ~StackNoticeExitRec();
  457. };
  458.  
  459.  
  460. StackNoticeExitRec::~StackNoticeExitRec() {
  461.     if (score->getGameWonOrLost()) NewGame();    // Force save.
  462. }
  463.  
  464.  
  465. StackNoticeExitRec noticeexit;
  466.  
  467. void StackInit() {
  468.     int i;
  469.     srandom(int(time(NULL)));
  470.  
  471.     for (i=0 ; i<NUMPLAYSTACK ; i++) {
  472.     playstack[i] = new StackPlayRec(i * 72 + 10, 114);
  473.     }
  474.     for (i=0 ; i<NUMSINGLESTACK ; i++) {
  475.     singlestack[i] = new StackSingleRec(i * 72 + 226, 10);
  476.     }
  477.     donestack[0] = new StackDoneRec(10, 10);
  478.     donestack[1] = new StackDoneRec(82, 10);
  479.     donestack[2] = new StackDoneRec(586, 10);
  480.     donestack[3] = new StackDoneRec(658, 10);
  481. }
  482.  
  483.  
  484.  
  485.  
  486. void DoAutoPlay() {
  487.     static Cursor waitcursor = NULL;
  488.     if (waitcursor == NULL) waitcursor = XCreateFontCursor(dpy, XC_watch);
  489.     XDefineCursor(dpy, toplevel, waitcursor);
  490.     DoRestart();
  491.     XFlush(dpy);
  492.     inautoplay = True;
  493.     int solvable = AutoPlay();
  494.     if (solvable) {
  495.     score->lostGame();
  496.     score->setMessage("Solvable.");
  497.     while (solutionhead) {
  498.         SolutionLog temp = solutionhead;
  499.         solutionhead = solutionhead->next;
  500.         Card card = cards[temp->suit][temp->rank];
  501.         if (temp->dest == -999) {
  502.         AutoMoves();
  503.         UndoBoundary();
  504.         } else if (temp->dest == -99) {
  505.         GetAvailableSingle()->addCard(card);
  506.         } else if (temp->dest <= NUMPLAYSTACK) {
  507.         playstack[temp->dest - 1]->addCard(card);
  508.         } else {
  509.         if (temp->rank == NUMVALUES - 1) { // King to empty stack.
  510.             for (int i=0 ; i<NUMPLAYSTACK ; i++) {
  511.             if (playstack[i]->getTopCard() == NULL) {
  512.                 playstack[i]->addCard(card);
  513.                 break;
  514.             }
  515.             }
  516.         } else {
  517.             cards[temp->suit][temp->rank+1]->getStack()->addCard(card);
  518.         }
  519.         }
  520.         delete temp;
  521.         XFlush(dpy);    // For debugging.
  522.     }
  523.     } else {
  524.     score->wonGame();
  525.     score->setMessage("Unsolvable.");
  526.     }
  527.     inautoplay = False;
  528.     XUndefineCursor(dpy, toplevel);
  529. }
  530.